package pl.shenlon.poker.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JComponent;
import javax.swing.SwingConstants;

import pl.shenlon.assets.Assets;
import pl.shenlon.poker.cards.Card;
import pl.shenlon.poker.cards.Hand;

public class HandComponent extends JComponent implements Observer {

	public static final int ALIGNMENT_LEFT, ALIGNMENT_CENTER, ALIGNMENT_RIGHT;

	public static final Image CARD_BACK_IMAGE;

	public static final int DEFAULT_OFFSET = 20;
	static {
		CARD_BACK_IMAGE = (BufferedImage) Assets.get("@cards/0");
		ALIGNMENT_LEFT = SwingConstants.LEFT;
		ALIGNMENT_CENTER = SwingConstants.CENTER;
		ALIGNMENT_RIGHT = SwingConstants.RIGHT;
	}

	private int alignment;

	private BufferedImage image;
	
	private final HandComponentModel model;

	private int offset;

	{
		offset = DEFAULT_OFFSET;
		alignment = SwingConstants.CENTER;
	}

	public HandComponent() {
		model = new DefaultHandComponentModel();
		model.addObserver(this);

	}

	public HandComponent(HandComponentModel model) {
		this.model = model;
		model.addObserver(this);
		prepareImageAndUpdateSize();
		
	}

	public int getAlignment() {
		return alignment;
	}

	public Card getCard(int index) {
		return model.getCard(index);
	}

	public int getCardsCount() {
		return model.getCardsCount();
	}

	public Hand getHand() {
		return model.getHand();
	}

	public HandComponentModel getModel() {
		return model;
	}

	@Override
	public void paintComponent(Graphics g) {
		g.drawImage(image, 0, 0, null);
	}

	private BufferedImage prepareImage() {
		int cardWidth = (Integer) Assets.get("@layout/card_width"), cardHeight = (Integer) Assets
				.get("@layout/card_height");

		int width = (model.getCardsCount() * (offset + cardWidth)), height = cardHeight;
		BufferedImage image = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = image.createGraphics();
		g.setColor(getBackground());

		g.fillRect(0, 0, width, height);
		int x = 0;
		switch (alignment) {
			case SwingConstants.LEFT :
				x = 0;
				break;
			case SwingConstants.RIGHT :
				x = offset;
				break;
			case SwingConstants.CENTER :
			default :
				x = offset / 2;
				break;
		}
		for (Card card : model.getHand().getCards()) {
			BufferedImage cardImage = (BufferedImage) (card.isFaceUp() == true
					? Assets.get("@cards/" + card.hashCode())
					: CARD_BACK_IMAGE);
			g.drawImage(cardImage, x, 0, null);
			x += cardWidth + offset;
		}
		g.dispose();
		return image;
	}

	private void prepareImageAndUpdateSize() {
		image = prepareImage();
		Dimension size = new Dimension(image.getWidth(), image.getHeight());
		setPreferredSize(size);
		setMinimumSize(size);
		setMaximumSize(size);
		repaint();
	}

	public void setAlignment(int alignment) {
		this.alignment = alignment;
		image = prepareImage();
		repaint();
	}

	@Override
	public void setBackground(Color color) {
		super.setBackground(color);
		image = prepareImage();
		repaint();
	}

	public void setCard(int index, Card card) {
		model.setCard(index, card);
	}

	public void setHand(Hand hand) {
		model.setHand(hand);
		hand.addObserver(model);
	}

	public void showCard(Card card) {
		model.showCard(card);
	}

	public void showCards() {
		model.showCards();
	}

	public void showCards(int... indexes) {
		model.showCards(indexes);
	}
	@Override
	public void update(Observable o, Object arg) {
		prepareImageAndUpdateSize();
	}
}